package demo2接口使用案例;
//类的克隆
class Person implements Cloneable{
    public int age;


    public Person(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                " age=" + age +
                " }";
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();//调用object类的方法来进行访问
       /* throws CloneNotSupportedException 这个是叫做抛出异常，所以我们要处理掉他，否则编译无法通过*/
    }
}
public class Test3 {
    public static void main(String[] args) throws CloneNotSupportedException{//必须在编译时处理
        Person person1 = new Person(10);
        /*
        在堆上，创建了一个对象，假设地址是0X98，那么在虚拟机栈上得到是这个对象的地址
         */

        System.out.println(person1);
        Person person2 = (Person)person1.clone();
        System.out.println(person1);

        /**
         * Person person1 = person.clone();这个其中所处新的错误：
         * 1.修饰符的错误，protected，这一步用super.clone()访问object类，来重写这个clone方法
         * 2.异常，clone方法的异常是受查异常/编译时异常，所以必须在编译时处理，(在main后面加入throws)
         * 3.向下转型，进行强制转换,因为我们用的是object类中的clone方法，所以返回类型是固定的object类，而不是构成了协变类型。所以我们要进行向下转型，将其转换为子类·
         * 进行了上述的操作，还是会报错：CloneNotSupportedException，不支持克隆
         * 4.所以我们要实现Cloneable这个接口，从而才能使用
         */
    }

    /*
    Cloneable是一个空接口，我们可以在IDEA去查看源码
    他是一个空窗口，也作为一种标记窗口，因为它用来证明当前类是可以被克隆的
     */

    /*
    clone方法源码：
    protected native Object clone() throws CloneNotSupportedException;
    本地方法native，用protected来访问的是不同包的子类，用super来访问父类object，
    所以通过重写这个clone的方法，来访问这个方法
     */

    //结论：通过clone的方法来进行克隆出堆中一个相同的一份的对象，但是两者（person和person2）在堆上不是一个位置，
    //所以person2这个克隆后的获得了一个新的地址0X8
    //所以我们通过return super.clone()来克隆

    //我的理解：clone方法实现的具体操作，用super.clone来访问，cloneable判断类是否支持克隆操作
}
